package com.iocup.keybastion.authorize.decision;


import com.google.common.collect.Sets;
import com.iocup.keybastion.annotion.HasPermission;
import com.iocup.keybastion.authorize.element.AuthElement;
import com.iocup.keybastion.annotion.HasAuthorization;
import com.iocup.keybastion.annotion.HasRole;
import com.iocup.keybastion.annotion.Logical;
import com.iocup.keybastion.authorize.HasAuthorizationProvider;
import com.iocup.keybastion.context.WebContextHolder;
import com.iocup.keybastion.core.profile.UserProfile;
import com.iocup.keybastion.utils.AuthUtils;
import com.pine.sunflower.core.validate.Validator;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Description: 根据条件判断是否具有角色或者权限码
 * @Author: xyjxust
 * @Date: 2022/3/22 13:48
 */
public class HasAuthorizationDecision implements AuthDecision {

    private HasAuthorizationProvider hasAuthorizationProvider;

    public HasAuthorizationDecision(HasAuthorizationProvider hasAuthorizationProvider) {
        Validator.build().validate(hasAuthorizationProvider == null, "HasAuthorizationProvider不能为空")
                .throwIfFail();
        this.hasAuthorizationProvider = hasAuthorizationProvider;
    }

    @Override
    public boolean decide(List<AuthElement> list, WebContextHolder webContext) {
        //如果权限元素为空
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }
        UserProfile userProfile = AuthUtils.getUserInfo();
        //用户未登录
        if (userProfile == null) {
            return false;
        }
        //
        Set<String> hasPermissions = hasAuthorizationProvider.getPermissions(userProfile.getLoginName(), userProfile.getDevice());
        Set<String> hasRoles = hasAuthorizationProvider.getRoles(userProfile.getLoginName(), userProfile.getDevice());
        //如果此时登录人权限码或角色都是为空
        if (CollectionUtils.isEmpty(hasPermissions) || CollectionUtils.isEmpty(hasRoles)) {
            return false;
        }
        return list.stream().anyMatch(authElement -> {
            Map<String, String> hasRole = authElement.getParam(HasAuthorization.ROLE);
            Map<String, String> hasPermission = authElement.getParam(HasAuthorization.PERMISSION);
            Logical logical = authElement.getParam(HasAuthorization.LOGICAL);
            String[] roles = hasRole.get(HasRole.VALUE).split(",");
            Logical roleLogical = Logical.valueOf(hasRole.get(HasRole.LOGICAL));
            String[] permissions = hasPermission.get(HasPermission.VALUE).split(",");
            Logical permissionsLogical = Logical.valueOf(hasPermission.get(HasPermission.LOGICAL));
            if (logical == Logical.ALL) {
                return AuthUtils.checkRoles(roleLogical,
                        Sets.newHashSet(roles), hasRoles)
                        && AuthUtils.checkPermissions(permissionsLogical,
                        Sets.newHashSet(permissions), hasPermissions);
            }
            return AuthUtils.checkRoles(roleLogical,
                    Sets.newHashSet(roles), hasRoles)
                    || AuthUtils.checkPermissions(permissionsLogical,
                    Sets.newHashSet(permissions), hasPermissions);
        });
    }

    @Override
    public String getType() {
        return DecisionType.hasAuthorization.name();
    }


}
